<?php
/**
 * 梭哈管理
 */
namespace app\chess;

Class Poker
{
    /**
     * 同花顺
     * @var integer
     */
    static public $Flush = 9;

    /**
     * 炸弹
     * @var integer
     */
    static public $Bomb = 8;

    /**
     * 葫芦
     * @var integer
     */
    static public $Gourd = 7;

    /**
     * 同花
     * @var integer
     */
    static public $WithColor = 6;

    /**
     * 顺子
     * @var integer
     */
    static public $Straight = 5;

    /**
     * 三条
     * @var integer
     */
    static public $Threefakind = 4;

    /**
     * 两对
     * @var integer
     */
    static public $TwoPair = 3;

    /**
     * 一对
     * @var integer
     */
    static public $OnePair = 2;

    /**
     * 散牌
     * @var integer
     */
    static public $Single = 1;

    /**
     * 点数
     * @var integer
     */
    static private $number = 0;

    /**
     * 牌型矩阵, 0->方块 1->梅花 2->红桃 3->黑桃
     * @var array
     */
    static private $matrix = [
        [0, 0, 0, 0], // 8
        [0, 0, 0, 0], // 9
        [0, 0, 0, 0], // 10
        [0, 0, 0, 0], // J
        [0, 0, 0, 0], // Q
        [0, 0, 0, 0], // K
        [0, 0, 0, 0], // A
    ];

    /**
     * 牌型矩阵, 0->方块 1->梅花 2->红桃 3->黑桃
     * @var array
     */
    private $initMatrix = [
        [0, 0, 0, 0], // 8
        [0, 0, 0, 0], // 9
        [0, 0, 0, 0], // 10
        [0, 0, 0, 0], // J
        [0, 0, 0, 0], // Q
        [0, 0, 0, 0], // K
        [0, 0, 0, 0], // A
    ];

    /**
     * 梭哈牌面矩阵 0->方块 1->梅花 2->红桃 3->黑桃
     * @var array
     */
    static private $poker = [
        [68, 48, 28, 8],  // 8
        [69, 49, 29, 9],  // 9
        [70, 50, 30, 10], // 10
        [71, 51, 31, 11], // J
        [72, 52, 32, 12], // Q
        [73, 53, 33, 13], // K
        [61, 41, 21, 1],  // A
    ];

    /**
     * 重新初始化
     *
     * @return [type] [description]
     */
    static private function reInit()
    {
        self::$matrix = [
            [0, 0, 0, 0], // 8
            [0, 0, 0, 0], // 9
            [0, 0, 0, 0], // 10
            [0, 0, 0, 0], // J
            [0, 0, 0, 0], // Q
            [0, 0, 0, 0], // K
            [0, 0, 0, 0], // A
        ];
        self::$number = 0;
    }

    /**
     * 判定同花顺
     *
     * @return boolean [description]
     */
    static private function isFlush()
    {
        $matrix = self::$matrix;

        $fisrt = [];
        for ($i = 0; $i < 3; $i++) {
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $fisrt = [$i, $j];
                    break 2;
                }
            }
        }

        if (empty($fisrt)) {
            return false;
        }

        if ($matrix[$fisrt[0]+1][$fisrt[1]] === 1 &&
            $matrix[$fisrt[0]+2][$fisrt[1]] === 1 &&
            $matrix[$fisrt[0]+3][$fisrt[1]] === 1 &&
            $matrix[$fisrt[0]+4][$fisrt[1]] === 1) {
            return true;
        }

        return false;
    }

    /**
     * 判定炸弹
     *
     * @return boolean [description]
     */
    static private function isBomb()
    {
        $matrix = self::$matrix;

        for ($i = 0; $i < count($matrix); $i++) {
            $count = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) $count++;
            }
            if ($count === 4) return true;
        }

        return false;
    }

    /**
     * 判定三条
     *
     * @return boolean false无
     */
    static private function isThreefakind()
    {
        $matrix = self::$matrix;

        for ($i = 0; $i < count($matrix); $i++) {
            $three = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $three++;
                }
            }
            if ($three === 3) return true;
        }

        return false;
    }

    /**
     * 判定对子
     *
     * @return boolean [description]
     */
    static private function isPairs()
    {
        $matrix = self::$matrix;

        $count = 0;
        for ($i = 0; $i < count($matrix); $i++) {
            $pairs = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $pairs++;
                }
            }
            if ($pairs === 2) {
                $count++;
            }
        }

        return $count;
    }

    /**
     * 判定同花
     *
     * @return boolean [description]
     */
    static private function isWithColor()
    {
        $matrix = self::$matrix;

        $count = 0;
        $index = 0;
        for ($i = 0; $i < count($matrix); $i++) {
            $color = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    if ($count === 0) {
                        $index = $j;
                        $color++;
                    } elseif ($index === $j) {
                        $color++;
                    }
                }
            }
            if ($color === 1) $count++;
        }

        if ($count === 5 && !self::isFlush()) {
            return true;
        }

        return false;
    }

    /**
     * 判定顺子
     *
     * @return boolean [description]
     */
    static public function isStraight()
    {
        $matrix = self::$matrix;

        $fisrt = [];
        for ($i = 0; $i < 3; $i++) {
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $fisrt = [$i, $j];
                    break 2;
                }
            }
        }

        if (empty($fisrt)) {
            return false;
        }

        $one = $fisrt[0];
        $count = 0;
        for ($i = $one+1; $i < $one+5; $i++) {
            $straight = 0;
            for ($j = 0; $j < count($matrix[$i]); $j++) {
                if ($matrix[$i][$j] === 1) {
                    $straight++;
                }
            }
            if ($straight === 1) $count++;
        }

        if ($count === 4 && !self::isFlush()) {
            return true;
        }

        return false;
    }

    /**
     * 手牌数据解析
     *
     * @param  [type] $array [description]
     * @return [type]        [description]
     */
    static public function dataParsingToHand($array)
    {
        $newArray = []; $count = 0;
        foreach ($array as $ak => $av) {
            // 得到牌的位置
            $temp = '';
            foreach ($av as $pk => $pv) {
                foreach ($pv as $dk => $dv) {
                    // 得到手牌
                    if (!$dv) continue 1; // 弃牌跳出循环
                    $temp .= $dk.',';
                }
            }
            if (!empty($temp)) {
                $temp = substr($temp, 0, strlen($temp)-1);
                $newArray[$count]['cards'] = $temp;
                $newArray[$count++]['uid'] = $ak;
            }
        }

        return $newArray;
    }

    /**
     * 设置牌型矩阵
     *
     * @param [type] $string [description]
     */
    static private function setMatrix($string)
    {
        $array = explode(',', $string);
        foreach ($array as $ak => $av) {
            foreach (self::$poker as $pk => $pv) {
                foreach ($pv as $k => $v) {
                    if ((int)$av === (int)$v) {
                        self::$matrix[$pk][$k] = 1;
                    }
                }
            }
        }

        self::setNumber();
        return self::$matrix;
    }

    /**
     * 设置点数
     */
    static private function setNumber()
    {
        foreach (self::$matrix as $k => $v) {
            foreach ($v as $zk => $zv) {
                if ($zv === 1) {
                    self::$number += ($k*4+1)+$zk;
                }
            }
        }
        return self::$number;
    }

    /**
     * 设置牌型
     */
    static public function setCardType()
    {
        $result = [
            'cardtype' => 0,
            'number' => self::$number
        ];

        // 判定牌型
        if (self::isFlush()) {
            $result['cardtype'] = self::$Flush;
        } elseif (self::isBomb()) {
            $result['cardtype'] = self::$Bomb;
        } elseif (self::isPairs() === 2) {
            $result['cardtype'] = self::$TwoPair;
        } elseif (self::isPairs() === 1 && self::isThreefakind()) {
            $result['cardtype'] = self::$Gourd;
        } elseif (self::isPairs() === 1 && !self::isThreefakind()) {
            $result['cardtype'] = self::$OnePair;
        } elseif (self::isPairs() === 0 && self::isThreefakind()) {
            $result['cardtype'] = self::$Threefakind;
        } elseif (self::isWithColor()) {
            $result['cardtype'] = self::$WithColor;
        } elseif (self::isStraight()) {
            $result['cardtype'] = self::$Straight;
        } else {
            $result['cardtype'] = self::$Single;
        }

        return $result;
    }

    /**
     * 设置牌面点数
     */
    public function setCardShowNumber($string)
    {
        $number = 0;
        $array = explode(',', $string);
        foreach ($array as $ak => $av) {
            foreach (self::$poker as $pk => $pv) {
                foreach ($pv as $k => $v) {
                    if ((int)$av === (int)$v) {
                        $this->initMatrix[$pk][$k] = 1;
                    }
                }
            }
        }

        foreach ($this->initMatrix as $k => $v) {
            foreach ($v as $zk => $zv) {
                if ($zv === 1) {
                    $number += ($k*4+1)+$zk;
                }
            }
        }

        return $number;
    }

    /**
     * 牌面全部打开
     *
     * @param  [type] $pos [description]
     * @return [type]      [description]
     */
    public function cardsOpen($pos)
    {
        $newPos = [];
        foreach ($pos as $k => $v) {
            $end = end($v);
            if (in_array(false, $end)) {
                continue 1;
            } else {
                foreach ($v as $sk => $sv) {
                    foreach ($sv as $ck => $cv) {
                        $newPos[$k][$sk][$ck] = true;
                    }
                }
            }
        }
        return $newPos;
    }

    /**
     * 获取牌类型和牌点数
     *
     * @param  [type] $pos [description]
     * @return [type]      [description]
     */
    static public function getCardsTypeAndNumber($pos)
    {
        $size = [];
        $count = 0;
        foreach ($pos as $k => $v) {
            if (count($v) != 5) {
                continue 1;
            }

            $posString = '';
            foreach ($v as $sk => $sv) {
                foreach ($sv as $ck => $cv) {
                    $posString .= $ck;
                    if ($sk != 4) {
                        $posString .= ',';
                        break 1;
                    } else {
                        break 2;
                    }
                }
            }
            self::setMatrix($posString);
            $cardType = self::setCardType();
            self::reInit();
            $size[$count++] = [
                'uid' => $k,
                'number' => $cardType['number'],
                'cardtype' => $cardType['cardtype']
            ];
        }
        return $size;
    }

    /**
     * 根据牌面的大小返回最大值的Uid
     *
     * @param  [type] $size [description]
     * @return [type]       [description]
     */
    static public function getMaxUidByCardsSize($size)
    {
        $maxArray = [
            'uid' => 0,
            'number' => 0,
            'cardtype' => 0
        ];
        foreach ($size as $k => $v) {
            if ($v['cardtype'] >= $maxArray['cardtype']) {
                if ($v['cardtype'] == $maxArray['cardtype']) {
                    if ($v['number'] > $maxArray['number']) {
                        $maxArray = $v;
                    }
                } else {
                    $maxArray = $v;
                }
            }
        }

        return $maxArray['uid'];
    }

    static public function t($pos)
    {
        dump(self::getCardsTypeAndNumber($pos));
    }
}
